﻿using Colorful.Furniture.BackgroundManagement;
using Colorful.Furniture.Enum;
using Colorful.Furniture.ErpCustomerManagement;
using Colorful.Furniture.ErpOrderManagement;
using Colorful.Furniture.Extensions;
using Colorful.Furniture.MpManagement;
using Colorful.Furniture.ResultManagement;
using FreeSql;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Data;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.ObjectMapping;
using IDatabase = StackExchange.Redis.IDatabase;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
using Colorful.Furniture.BasicDataManagement;
using Microsoft.Extensions.Options;
using Colorful.Furniture.InterfaceUpstream;
using Volo.Abp.Auditing;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading;
using Colorful.Furniture.View;
using Essensoft.Paylink.Alipay.Domain;
using Volo.Abp;
using Hangfire;

namespace Colorful.Furniture.InterfaceDownstream;

/// <summary>
/// 下游接口服务
/// </summary>
[DisableAuditing]
public class RechargeAppService : ApplicationService
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IFreeSql _freeSql;
    private readonly IObjectMapper _objectMapper;
    private readonly ILogger<WechatMpJsSdkAppService> _logger;
    private readonly IBaseRepository<RechargeOrder> _rechargeOrderRepository;
    private readonly IBackgroundJobManager _backgroundJobManager;
    private readonly IDatabase _redisDb;
    private readonly FileConfig _fileConfig;

    public RechargeAppService(
        IHttpContextAccessor httpContextAccessor,
        IFreeSql freeSql,
        IObjectMapper objectMapper,
        ILogger<WechatMpJsSdkAppService> logger,
        IConnectionMultiplexer connectionMultiplexer,
        IBaseRepository<RechargeOrder> rechargeOrderRepository,
        IBackgroundJobManager backgroundJobManager,
        IOptions<FileConfig> fileConfig
    )
    {
        _httpContextAccessor = httpContextAccessor;
        _freeSql = freeSql;
        _objectMapper = objectMapper;
        _logger = logger;
        _rechargeOrderRepository = rechargeOrderRepository;
        _backgroundJobManager = backgroundJobManager;
        _redisDb = connectionMultiplexer.GetDatabase();
        _fileConfig = fileConfig.Value;
    }

    /// <summary>
    /// 充值订单下单接口
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisableAuditing]
    public async Task<SuccessOrderResultDto> OrderAsync([FromBody] CreateRechargeOrderInputDto input)
    {
        var uow = _freeSql.CreateUnitOfWork();
        uow.IsolationLevel = IsolationLevel.ReadUncommitted;

        //检查商户信息
        var customerInfo = await _freeSql.Select<Customer>()
            .Where(x => x.Code == input.MerchantId)
            .WithTransaction(uow.GetOrBeginTransaction())
            .FirstAsync();
        if (customerInfo == null)
        {
            uow.Commit();

            return new SuccessOrderResultDto
            {
                Code = "1002",
                Message = "无效商户信息"
            };
        }

        //获取商品关系视图
        var product = await _freeSql.Select<ViewInventory>()
            .Where(x => x.ProductNo == input.ProductNo && x.CustomerCode == input.MerchantId)
            .WithTransaction(uow.GetOrBeginTransaction())
            .OrderByDescending(x => x.Sort)
            .OrderBy(x => x.ProductAddTime)
            .FirstAsync();
        if (product == null)
        {
            uow.Commit();

            return new SuccessOrderResultDto
            {
                Code = "1006",
                Message = $"【{input.ProductNo}】商品未开通"
            };
        }


        var rechargeTime = DateTime.Now;
        var orderNo = $"{rechargeTime:yyMMddHHmmssfff}{CommonUtils.Number(2)}";
        
        //判断是否存在
        var redisInfo = await _redisDb.StringGetAsync($"{_fileConfig.RedisName}:Order:{orderNo}");
        while (redisInfo.HasValue) //Redis中存在订单编号，则重新生成订单编号
        {
            var orderNoOld = orderNo;
            orderNo = $"{DateTime.Now:yyMMddHHmmssfff}{CommonUtils.Number(2)}";
            _logger.LogWarning($"订单编号重复，重新生成订单编号：OrderDownNoOld = {orderNoOld}，OrderDownNo = {orderNo}");
        }

        _logger.LogWarning($"接收充值提单信息，OrderDownNo = {orderNo}；请求体：{{\"merchantId\": {input.MerchantId},\"outTradeNo\": \"{input.OutTradeNo}\",\"productNo\": \"{input.ProductNo}\"," +
                           $"\"rechargeAccount\": \"{input.RechargeAccount}\",\"number\": {input.Number},\"notifyUrl\": \"{input.NotifyUrl}\",\"sign\": \"{input.Sign}\" }}");

        try
        {
            //提单信息写入缓存
            await _redisDb.StringSetAsync($"{_fileConfig.RedisName}:Order:{orderNo}",
                JsonConvert.SerializeObject(new
                {
                    OrderNo = orderNo,
                    input.MerchantId,
                    input.OutTradeNo,
                    input.ProductNo,
                    input.RechargeAccount,
                    input.Number,
                    input.NotifyUrl,
                    input.Sign,
                    input.EndCustomerIp,
                    PayAmount = 0,
                    RechargeTime = rechargeTime
                }), TimeSpan.FromHours(4));

            //调用后台作业-订单提交操作
            await _backgroundJobManager.EnqueueAsync(new RechargeJobArgs
            {
                OrderNo = orderNo
            });


        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }





        uow.Commit();

        return new SuccessOrderResultDto
        {
            Code = "1002",
            Message = "无效商户信息"
        };

    }



}

